#pragma once
#include<iostream>
#include"Record.h"
#include"IndexRecord.h"
#include"ResourceInfo.h"
#include"ResourceLock.h"
using namespace std;

class ResourceManage{
private:

    ResourceLock* resourceLock;

    QReadWriteLock* snapShotLock;

    QReadWriteLock* holdLock;

    static int lockWaitTime; //单次获取锁最大等待时间 （单位：毫秒）

protected:

    ResourceInfo resourceInfo;

public:

    static void setLockWaitTime(const int& lwt){
        lockWaitTime = lwt;
    }

    ResourceManage(const ResourceInfo& ri):
        resourceInfo(ri)
    {
        resourceLock = new ResourceLock();
        snapShotLock = new QReadWriteLock(QReadWriteLock::Recursive);
        holdLock = new QReadWriteLock(QReadWriteLock::Recursive);
    }

    virtual ~ResourceManage(){
        MemUtil::clearPtrMem(resourceLock);
        MemUtil::clearPtrMem(snapShotLock);
        MemUtil::clearPtrMem(holdLock);
    }

    void getResLock(const LOCKTYPE& lockType){ //依据参数请求锁，如果在指定时间后仍未获取到，认为死锁 在具体业务中回滚。
        LockUtil::getLock(resourceLock, lockType, lockWaitTime);
    }

    void releaseResLock(){
        resourceLock->releaseResource();
    }

    void getSnapShotLock(const LOCKTYPE& lockType){
        LockUtil::getLock(snapShotLock, lockType, lockWaitTime);
    }

    void releaseSnapShotLock(){
        snapShotLock->unlock();
    }

    void getHoldLock(const LOCKTYPE& lockType){
        LockUtil::getLock(holdLock, lockType);      //不会发生死锁  不限制时间
    }

    void releaseHoldLock(){
        holdLock->unlock();
    }

    ResourceInfo getResourceInfo() const {
        return resourceInfo;
    }

    DISKTYPE getDiskType() const {
        return resourceInfo.getDiskType();
    }

    //全量读写接口
    virtual void writeToDisk() = 0;

    virtual void readFromDisk() = 0;

    //事务提交回滚接口
    virtual vector<Record*> getComitRecords(){return {};}

    virtual vector<IndexRecord*> getComitIndexRecords(){return {};}

    virtual vector<uint64_t> getComitBitMapRecords(){return {};}

    virtual void memRollBack() = 0;

    //制作快照接口
    virtual void makeSnapShot() = 0;

};



bool resCmp(const ResourceManage* res1, const ResourceManage* res2){
    return resInfoCmp(res1->getResourceInfo(), res2->getResourceInfo());
}



class ResourceMemManager{


    class AsyncClearRes : public QRunnable{
    private:
        ResourceManage* res;

    public:
        AsyncClearRes(ResourceManage* rs){
            this->res = rs;
        }

        virtual void run(){
            res->getHoldLock(WRITE);    //等待独占此持有锁 当独占此资源时 才能释放
            MemUtil::clearPtrMem(res);
        }
    };

public:
    static void asyncClearResMem(ResourceManage* res){
        ThreadPools::resourceAsyncClearThreadPool->start(new AsyncClearRes(res));
    }
};
